package com.hospital.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hospital.domain.*;
import com.hospital.service.*;
import com.hospital.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("/bloodTransfusionRecord")
@CrossOrigin(origins = "*",maxAge = 3600)
public class BloodTransfusionRecordController {

    @Autowired
    private BloodTransfusionRecordService bloodTransfusionRecordService;

    @Autowired
    private HospitalService hospitalService;

    @Autowired
    private PatientService patientService;

    @Autowired
    private BloodProductTypeService bloodProductTypeService;

    @Autowired
    private DoctorService doctorService;

    @GetMapping("bloodUsing")
    public R bloodUsing(){
        LambdaQueryWrapper<BloodTransfusionRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(BloodTransfusionRecord::getHospitalId,BloodTransfusionRecord::getVolume);
        List<Map<String, Object>> maps = bloodTransfusionRecordService.listMaps(queryWrapper);
        for (Map<String, Object> map : maps) {
            int hospitalId = (int) map.get("hospital_id");
            Hospital hospital = hospitalService.getById(hospitalId);
            map.put("hospitalName",hospital.getName());
            map.remove("hospital_id");
        }

        Map<String, BigDecimal> hospitalVolumeMap = new HashMap<>();

        for (Map<String, Object> map : maps) {
            String hospitalName = (String) map.get("hospitalName");
            BigDecimal volume = (BigDecimal) map.get("volume");
            hospitalVolumeMap.put(hospitalName, hospitalVolumeMap.getOrDefault(hospitalName, BigDecimal.ZERO).add(volume));
        }

        List<Map<String, Object>> result = new ArrayList<>();
        for (Map.Entry<String, BigDecimal> entry : hospitalVolumeMap.entrySet()) {
            Map<String, Object> mergedRecord = new HashMap<>();
            mergedRecord.put("hospitalName", entry.getKey());
            mergedRecord.put("volume", entry.getValue());
            result.add(mergedRecord);
        }
        return R.ok().put("data",result);
    }

    @GetMapping("/getRate")
    public R getRate(){
        LambdaQueryWrapper<BloodTransfusionRecord> queryWrapper = new LambdaQueryWrapper<>();
        int count = bloodTransfusionRecordService.count(queryWrapper);
        log.info("count:{}",count);
        queryWrapper.isNotNull(BloodTransfusionRecord::getAdverseReactionId);
        int rate = bloodTransfusionRecordService.count(queryWrapper);
        log.info("rate:{}",rate);
        return R.ok().put("data",(double)rate/count);
    }

    @GetMapping("/getRecord")
    public R getRecord(@RequestParam(defaultValue = "1") Integer pageNum,
                       @RequestParam(defaultValue = "3") Integer pageSize){
        Page<BloodTransfusionRecord> page = new Page<>(pageNum,pageSize);
        Page<BloodTransfusionRecord> hospitalPage = bloodTransfusionRecordService.page(page);
        List<BloodTransfusionRecord> records = hospitalPage.getRecords();
        for (BloodTransfusionRecord record : records) {
            int hospitalId = record.getHospitalId();
            Hospital hospital = hospitalService.getById(hospitalId);
            int patientId = record.getPatientId();
            Patient patient = patientService.getById(patientId);
            int bloodProductId = record.getBloodProductTypeId();
            BloodProductType bloodProductType = bloodProductTypeService.getById(bloodProductId);
            record.setHospitalName(hospital.getName());
            record.setPatientName(patient.getName());
            record.setProductTypeName(bloodProductType.getProductName());
        }
        int total = bloodTransfusionRecordService.count();
        return R.ok().put("data",records).put("total",total);
    }

//    @Cacheable(value = "bloodTransfusionRecord",key = "#root.methodName")
    @GetMapping("list")
    public R list(){
        Map<String,Object> map = new HashMap<>();
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        for (BloodTransfusionRecord record : records) {
            int hospitalId = record.getHospitalId();
            Hospital hospital = hospitalService.getById(hospitalId);
            int patientId = record.getPatientId();
            Patient patient = patientService.getById(patientId);
            int bloodProductId = record.getBloodProductTypeId();
            BloodProductType bloodProductType = bloodProductTypeService.getById(bloodProductId);
            int doctorId = record.getDoctorId();
            Doctor doctor = doctorService.getById(doctorId);
            record.setDoctorName(doctor.getName());
            record.setHospitalName(hospital.getName());
            record.setPatientName(patient.getName());
            record.setProductTypeName(bloodProductType.getProductName());
        }
        map.put("data",records);
        return R.ok().put("data",map);
    }

    @GetMapping("getData")
    public R getData(){
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        Double[] mount = new Double[7];
        Arrays.fill(mount, 0.0);
        for(BloodTransfusionRecord record : records){
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if (month.equals("05")) mount[0]+=record.getVolume();
            else if (month.equals("06")) mount[1]+=record.getVolume();
            else if (month.equals("07")) mount[2]+=record.getVolume();
            else if (month.equals("08")) mount[3]+=record.getVolume();
            else if (month.equals("09")) mount[4]+=record.getVolume();
            else if (month.equals("10")) mount[5]+=record.getVolume();
            else if (month.equals("11")) mount[6]+=record.getVolume();
        }
        return R.ok().put("data",mount);
    }

//    @Cacheable(value = "bloodTransfusionRecord",key = "#hospitalId")
    @GetMapping("getRecordByHospital")
    public R getRecordByHospital() {
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        Double[] mount = new Double[7];
        Arrays.fill(mount, 0.0);
        for(BloodTransfusionRecord record : records){
            if(record.getHospitalId() != 1) continue;
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if (month.equals("05")) mount[0]+=record.getVolume();
            else if (month.equals("06")) mount[1]+=record.getVolume();
            else if (month.equals("07")) mount[2]+=record.getVolume();
            else if (month.equals("08")) mount[3]+=record.getVolume();
            else if (month.equals("09")) mount[4]+=record.getVolume();
            else if (month.equals("10")) mount[5]+=record.getVolume();
            else if (month.equals("11")) mount[6]+=record.getVolume();
        }
        return R.ok().put("data",mount);
    }

//    @Cacheable(value = "bloodTransfusionRecord",key = "#adverseReactionId")
    @GetMapping("getRecordByAdverseAll")
    public R getRecordByAdverseAll() {
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[12];
        Arrays.fill(mount, 0);
        for(BloodTransfusionRecord record : records){
            if(record.getAdverseReactionId()==1) continue;
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if (month.equals("01")) mount[0]++;
            else if(month.equals("02")) mount[1]++;
            else if (month.equals("03")) mount[2]++;
            else if (month.equals("04")) mount[3]++;
            else if (month.equals("05")) mount[4]++;
            else if (month.equals("06")) mount[5]++;
            else if (month.equals("07")) mount[6]++;
            else if (month.equals("08")) mount[7]++;
            else if (month.equals("09")) mount[8]++;
            else if (month.equals("10")) mount[9]++;
            else if (month.equals("11")) mount[10]++;
            else if (month.equals("12")) mount[11]++;
        }
        return R.ok().put("data",mount);
    }

    @GetMapping("getRecordByAdverse")
    public R getRecordByAdverse() {
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[7];
        Arrays.fill(mount, 0);
        for(BloodTransfusionRecord record : records){
            if(record.getAdverseReactionId()==1 || record.getHospitalId()!=1) continue;
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if (month.equals("05")) mount[0]++;
            else if (month.equals("06")) mount[1]++;
            else if (month.equals("07")) mount[2]++;
            else if (month.equals("08")) mount[3]++;
            else if (month.equals("09")) mount[4]++;
            else if (month.equals("10")) mount[5]++;
            else if (month.equals("11")) mount[6]++;
        }
        return R.ok().put("data",mount);
    }

    @GetMapping("getRecordByAdverseBloodTpye")
    public R getRecordByAdverseBloodTpye() {
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[5];
        for(BloodTransfusionRecord record:records){
            if(record.getAdverseReactionId()==1) continue;
            if(record.getBloodType().equals("A")){
                mount[0]+=record.getVolume();
            }else if(record.getBloodType().equals("B")){
                mount[1]+=record.getVolume();
            }else if(record.getBloodType().equals("AB")){
                mount[2]+=record.getVolume();
            }else if(record.getBloodType().equals("O")){
                mount[3]+=record.getVolume();
            }else {
                mount[4] += record.getVolume();
            }
        }
        return R.ok().put("data",mount);
    }

    @GetMapping("getBloodUsing")
    public R getBloodUsing(){
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[5];
        for(BloodTransfusionRecord record:records){
            if(record.getHospitalId()!=1) continue;
            if(record.getBloodType().equals("A")){
                mount[0]+=record.getVolume();
            }else if(record.getBloodType().equals("B")){
                mount[1]+=record.getVolume();
            }else if(record.getBloodType().equals("AB")){
                mount[2]+=record.getVolume();
            }else if(record.getBloodType().equals("O")){
                mount[3]+=record.getVolume();
            }else {
                mount[4] += record.getVolume();
            }
        }
        return R.ok().put("data",mount);
    }

    @GetMapping("getBloodUsingAll")
    public R getBloodUsingAll(){
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[5];
        for(BloodTransfusionRecord record:records){
            if(record.getBloodType().equals("A")){
                mount[0]+=record.getVolume();
            }else if(record.getBloodType().equals("B")){
                mount[1]+=record.getVolume();
            }else if(record.getBloodType().equals("AB")){
                mount[2]+=record.getVolume();
            }else if(record.getBloodType().equals("O")){
                mount[3]+=record.getVolume();
            }else {
                mount[4] += record.getVolume();
            }
        }
        return R.ok().put("data",mount);
    }

//    @CachePut(value = "bloodTransfusionRecord",key = "#bloodTransfusionRecord.id")
    @PostMapping("save")
    public R save(@RequestBody BloodTransfusionRecord bloodTransfusionRecord){
        return R.ok("添加成功").put("list",bloodTransfusionRecordService.save(bloodTransfusionRecord));
    }

//    @CachePut(value = "bloodTransfusionRecord",key = "#bloodTransfusionRecord.id")
    @PutMapping("/update")
    public R update(@RequestBody BloodTransfusionRecord bloodTransfusionRecord) {
        if(!bloodTransfusionRecordService.updateById(bloodTransfusionRecord))
            return R.error("更新失败");
        else
            return R.ok("更新成功").put("list",bloodTransfusionRecordService.updateById(bloodTransfusionRecord));
    }

//    @CacheEvict(value = "bloodTransfusionRecord",allEntries = true)
    @DeleteMapping("/delete")
    public R delete(@RequestBody List<Integer> ids){
        if(!bloodTransfusionRecordService.removeByIds(ids))
            return R.error("删除失败");
        else
            return R.ok("删除成功").put("list",bloodTransfusionRecordService.removeByIds(ids));
    }

//    @Cacheable(value = "bloodTransfusionRecord",key = "#id")
    @GetMapping("getRecordByVolumeAll")
    public R getRecordByVolumeAll() {
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[7];
        Arrays.fill(mount, 0);
        for(BloodTransfusionRecord record : records){
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if (month.equals("05")) mount[0]+=record.getVolume();
            else if (month.equals("06")) mount[1]+=record.getVolume();
            else if (month.equals("07")) mount[2]+=record.getVolume();
            else if (month.equals("08")) mount[3]+=record.getVolume();
            else if (month.equals("09")) mount[4]+=record.getVolume();
            else if (month.equals("10")) mount[5]+=record.getVolume();
            else if (month.equals("11")) mount[6]+=record.getVolume();
        }
        return R.ok().put("data",mount);
    }

//    @Cacheable(value = "bloodTransfusionRecord",key = "#id")
    @GetMapping("getRecordByVolume")
    public R getRecordByVolume() {
        List<BloodTransfusionRecord> records = bloodTransfusionRecordService.list();
        int[] mount = new int[12];
        Arrays.fill(mount, 0);
        for(BloodTransfusionRecord record : records){
            if(record.getHospitalId()!=1) continue;
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if (month.equals("01")) mount[0]+=record.getVolume();
            else if(month.equals("02")) mount[1]+=record.getVolume();
            else if (month.equals("03")) mount[2]+=record.getVolume();
            else if (month.equals("04")) mount[3]+=record.getVolume();
            else if (month.equals("05")) mount[4]+=record.getVolume();
            else if (month.equals("06")) mount[5]+=record.getVolume();
            else if (month.equals("07")) mount[6]+=record.getVolume();
            else if (month.equals("08")) mount[7]+=record.getVolume();
            else if (month.equals("09")) mount[8]+=record.getVolume();
            else if (month.equals("10")) mount[9]+=record.getVolume();
            else if (month.equals("11")) mount[10]+=record.getVolume();
            else if (month.equals("12")) mount[11]+=record.getVolume();
        }
        return R.ok().put("data",mount);
    }

//    @Cacheable(value = "bloodTransfusionRecord",key = "#id")
    @GetMapping("getByMonthByBloodType")
    public R getByMonthByBloodType(){
        List<BloodTransfusionRecord> list = bloodTransfusionRecordService.list();
        Map<String,Double> map1 = new HashMap<>();
        Map<String,Double> map2 = new HashMap<>();
        Map<String,Double> map3 = new HashMap<>();
        Map<String,Double> map4 = new HashMap<>();
        Map<String,Double> map5 = new HashMap<>();
        Map<String,Double> map6 = new HashMap<>();
        Map<String,Double> map7 = new HashMap<>();
        for(BloodTransfusionRecord record:list){
            if (record.getHospitalId()!=1) continue;
            Date date = record.getTransfusionDate();
            SimpleDateFormat monthFormat = new SimpleDateFormat("MM");
            String month = monthFormat.format(date);
            if(month.equals("05")){
                if(record.getBloodType().equals("A")) map1.put("A",map1.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map1.put("B",map1.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map1.put("AB",map1.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map1.put("O",map1.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map1.put("Rare",map1.getOrDefault("Rare",0.0)+record.getVolume());
            }else if(month.equals("06")){
                if(record.getBloodType().equals("A")) map2.put("A",map2.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map2.put("B",map2.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map2.put("AB",map2.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map2.put("O",map2.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map2.put("Rare",map2.getOrDefault("Rare",0.0)+record.getVolume());
            }else if(month.equals("07")){
                if(record.getBloodType().equals("A")) map3.put("A",map3.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map3.put("B",map3.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map3.put("AB",map3.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map3.put("O",map3.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map3.put("Rare",map3.getOrDefault("Rare",0.0)+record.getVolume());
            }else if(month.equals("08")){
                if(record.getBloodType().equals("A")) map4.put("A",map4.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map4.put("B",map4.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map4.put("AB",map4.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map4.put("O",map4.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map4.put("Rare",map4.getOrDefault("Rare",0.0)+record.getVolume());
            }else if(month.equals("09")){
                if(record.getBloodType().equals("A")) map5.put("A",map5.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map5.put("B",map5.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map5.put("AB",map5.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map5.put("O",map5.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map5.put("Rare",map5.getOrDefault("Rare",0.0)+record.getVolume());
            }else if(month.equals("10")){
                if(record.getBloodType().equals("A")) map6.put("A",map6.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map6.put("B",map6.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map6.put("AB",map6.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map6.put("O",map6.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map6.put("Rare",map6.getOrDefault("Rare",0.0)+record.getVolume());
            }else if(month.equals("11")){
                if(record.getBloodType().equals("A")) map7.put("A",map7.getOrDefault("A",0.0)+record.getVolume());
                if(record.getBloodType().equals("B")) map7.put("B",map7.getOrDefault("B",0.0)+record.getVolume());
                if(record.getBloodType().equals("AB")) map7.put("AB",map7.getOrDefault("AB",0.0)+record.getVolume());
                if(record.getBloodType().equals("O")) map7.put("O",map7.getOrDefault("O",0.0)+record.getVolume());
                if(record.getBloodType().equals("Rare")) map7.put("Rare",map7.getOrDefault("Rare",0.0)+record.getVolume());
            }
        }
        List<Map<String,Double>> list1 = new ArrayList<>();
        list1.add(map1);
        list1.add(map2);
        list1.add(map3);
        list1.add(map4);
        list1.add(map5);
        list1.add(map6);
        list1.add(map7);
        return R.ok().put("data",list1);
    }
}
